package com.wlz.netty;

import com.wlz.push.server.NettyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import sun.nio.ch.Net;

/**
 * @author wlz
 * @date 2022-07-06  11:31 下午
 */
@Slf4j
public class MyNettyServer {

    public static void main(String[] args) {

        // 创建两个线程组 bossGroup 和 workerGroup，含有的子线程 NioEventLoopGroup 的个数默认为cpu 核数的两倍
        // bossGroup 只是处理连接请求， workerGroup 负责 和客户端业务处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 创建 服务器端 的启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(bossGroup,workerGroup)// 设置两个线程组
                    .channel(NioServerSocketChannel.class) // 使用 NioServerSocketChannel 作为服务器的通道实现
                    // 初始化服务器连接队列大小，服务端处理客户端连接请求是顺序处理的，所以同一时间只能处理一个客户端连接.
                    // 多个客户端同时过来的时候，服务端将不能处理的客户端连接请求放到队列中等待处理
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() { //  创建通道初始化对象，设置初始参数

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 对 workerGroup 的 SocketChannel 设置 处理器
                            socketChannel.pipeline().addLast(new MyNettyServerHandler());
                        }
                    });

            log.info("netty server start ....");

            // 绑定一个端口 并且同步，生成了一个 ChannelFuture 异步对象，通过 isDone() 等方法可以判断异步事件的执行情况
            // 启动服务器(并绑定端口)， bind 是异步操作，sync 方法是 等待异步操作执行完毕
            ChannelFuture cf = bootstrap.bind(9000).sync();

            // 给 cf 注册监听器，监听关心的事件
          /*  cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (cf.isSuccess()) {
                        log.info("监听端口9000成功");
                    }else {
                        log.info("监听端口9000失败");
                    }
                }
            });*/

            // 对通道关闭进行监听，closeFuture 是异步操作，监听通道关闭
            // 通过 sync 方法 同步等待 通道关闭 处理完毕，这里会阻塞等待 通道关闭完成
            cf.channel().closeFuture().sync();


        } catch (Exception e) {
            log.error("error: {}",e);
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }


    }
}
